#pragma once

#include <future>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include <string>

class Action
{
  protected:
    std::string type;
    std::string name;
    std::chrono::milliseconds duration;

  public:
    std::string Type() const { return type; }
    std::string Name() const { return name; }

  protected:
    virtual bool Execute() = 0;
    virtual void Terminate() = 0;

  public:
    Action(const std::string &type, const std::string &name, const std::chrono::milliseconds &duration)
        : type(type), name(name), duration(duration)
    {
    }
    Action(const nlohmann::json &j)
    {
        j.at("type").get_to(type);
        j.at("name").get_to(name);
        duration = std::chrono::milliseconds(100);
    }

    std::future<bool> AsyncExecute()
    {
        spdlog::info("Start executing action <{}>:{}", type, name);
        return std::async(std::launch::async, [this]() { return this->Execute(); });
    }
    std::future<void> AsyncTerminate()
    {
        spdlog::info("Terminating shell action <{}>:{}", type, name);
        return std::async(std::launch::async, [this]() { this->Terminate(); });
    }
};